=begin pod

=TITLE class Mix

=SUBTITLE Immutable collection of distinct objects with Real weights

    class Mix does Mixy { }

A C<Mix> is an immutable mix, meaning a collection of distinct elements in no
particular order that each have a real-number weight assigned to them. (For
I<mutable> mixes, see L<MixHash> instead.)

C<Mix>es are often used for performing weighted random selections - see
L<.roll|roll>.

Objects/values of any type are allowed as mix elements. Within a C<Mix>, items
that would compare positively with the L<===> operator are considered the same
element, with a combined weight.

=begin code
my $recipe = (butter => 0.22, sugar => 0.1,
              flour => 0.275, sugar => 0.02).Mix;

say $recipe.elems;      # OUTPUT: «3␤»
say $recipe.keys.sort;  # OUTPUT: «butter flour sugar␤»
say $recipe.pairs.sort; # OUTPUT: «"butter" => 0.22 "flour" => 0.275 "sugar" => 0.12␤»
say $recipe.total;      # OUTPUT: «0.615␤»
=end code

C<Mix>es can be treated as object hashes using the C<{ }> postcircumfix
operator, which returns the corresponding numeric weight for keys that are
elements of the mix, and C<0> for keys that aren't:

    my $recipe = (butter => 0.22, sugar => 0.1,
                  flour => 0.275, sugar => 0.02).Mix;
    say $recipe<butter>;     # OUTPUT: «0.22␤»
    say $recipe<sugar>;      # OUTPUT: «0.12␤»
    say $recipe<chocolate>;  # OUTPUT: «0␤»

=head1 Creating C<Mix> objects

C<Mix>es can be composed using the L<mix|#sub mix> subroutine (or C<Mix.new>,
for which it is a shorthand). Any positional parameters, regardless of their
type, become elements of the mix - with a weight of C<1> for each time the
parameter occurred:

    my $n = mix "a", "a", "b" => 0, "c" => 3.14;
    say $n.keys.map(&WHAT);  # OUTPUT: «((Str) (Pair) (Pair))␤»
    say $n.pairs;            # OUTPUT: «(a => 2 (c => 3.14) => 1 (b => 0) => 1)␤»

Alternatively, the C<.Mix> coercer (or its functional form, C<Mix()>) can be
called on an existing object to coerce it to a C<Mix>. Its semantics depend on
the type and contents of the object. In general it evaluates the object in list
context and creates a mix with the resulting items as elements, although for
Hash-like objects or Pair items, only the keys become elements of the mix, and
the (cumulative) values become the associated numeric weights:

    my $n = ("a", "a", "b" => 0, "c" => 3.14).Mix;
    say $n.keys.map(&WHAT);  # OUTPUT: «((Str) (Str))␤»
    say $n.pairs;            # OUTPUT: «(a => 2 c => 3.14)␤»

=head1 Operators

=for comment
TODO: Expand this section (using the corresponding section in lib/Type/Bag.pod
as a guide) after ab5tract's set/bag/mix operator redesign.

See L<Set/Bag Operators|/language/setbagmix#Set/Bag_Operators> for a complete list of set and bag operators
with detailed explanations.

=head2 sub mix

    sub mix(*@args --> Mix)

Creates a new C<Mix> from C<@args>.

=head1 Methods

=head2 method Bag

Defined as:

    method Bag (--> Bag:D)

Coerces the C<Mix> to a L«C<Bag>|/type/Bag». The weights are convert to L«C<Int>|/type/Int»,
which means the number of keys in the resulting C<Bag> can be fewer than in the
original C<Mix>, if any of the weights are negative or truncate to zero.

=head2 method BagHash

Defined as:

    method BagHash (--> BagHash:D)

Coerces the C<Mix> to a L«C<BagHash>|/type/BagHash». The weights are convert to L«C<Int>|/type/Int»,
which means the number of keys in the resulting C<BagHash> can be fewer than in the
original C<Mix>, if any of the weights are negative or truncate to zero.

=head1 See Also

L<Sets, Bags, and Mixes|/language/setbagmix>

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
